bitkeeper revision 1.1564.1.6 (429e165dilv2Yl2AOW9ZyHrCpVrJDg)
authordjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Wed, 1 Jun 2005 20:11:09 +0000 (20:11 +0000)
committerdjm@kirby.fc.hp.com <djm@kirby.fc.hp.com>
Wed, 1 Jun 2005 20:11:09 +0000 (20:11 +0000)
Add counters for hyperprivops and reflections
Preliminary work for fast break reflection
Signed-off by: Dan Magenheimer <dan.magenheimer@hp.com>

xen/arch/ia64/asm-offsets.c
xen/arch/ia64/dom_fw.c
xen/arch/ia64/domain.c
xen/arch/ia64/hyperprivop.S
xen/arch/ia64/ivt.S
xen/arch/ia64/privop.c
xen/arch/ia64/process.c
xen/include/asm-ia64/domain.h

index 6518e29bdb6bf1af3d5219e3d160ffa8c2000fa5..d2e5fcff4e6e691544527288e26585a21f3235ac 100644 (file)
@@ -45,10 +45,15 @@ void foo(void)
        DEFINE(XSI_PSR_IC, (SHAREDINFO_ADDR+offsetof(vcpu_info_t, arch.interrupt_collection_enabled)));
        DEFINE(XSI_PSR_I_OFS, offsetof(vcpu_info_t, arch.interrupt_delivery_enabled));
        DEFINE(XSI_IIP_OFS, offsetof(vcpu_info_t, arch.iip));
+       DEFINE(XSI_IPSR, (SHAREDINFO_ADDR+offsetof(vcpu_info_t, arch.ipsr)));
        DEFINE(XSI_IPSR_OFS, offsetof(vcpu_info_t, arch.ipsr));
        DEFINE(XSI_IFS_OFS, offsetof(vcpu_info_t, arch.ifs));
+       DEFINE(XSI_IIM_OFS, offsetof(vcpu_info_t, arch.iim));
        DEFINE(XSI_BANKNUM_OFS, offsetof(vcpu_info_t, arch.banknum));
+       DEFINE(XSI_BANK0_OFS, offsetof(vcpu_info_t, arch.bank0_regs[0]));
+       DEFINE(XSI_BANK1_OFS, offsetof(vcpu_info_t, arch.bank1_regs[0]));
        DEFINE(XSI_METAPHYS_OFS, offsetof(vcpu_info_t, arch.metaphysical_mode));
+       DEFINE(XSI_PRECOVER_IFS_OFS, offsetof(vcpu_info_t, arch.precover_ifs));
        DEFINE(XSI_INCOMPL_REG_OFS, offsetof(vcpu_info_t, arch.incomplete_regframe));
        DEFINE(XSI_PEND_OFS, offsetof(vcpu_info_t, arch.pending_interruption));
        DEFINE(XSI_RR0_OFS, offsetof(vcpu_info_t, arch.rrs[0]));
@@ -66,6 +71,8 @@ void foo(void)
 
        DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct exec_domain, arch.metaphysical_rr0));
        DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct exec_domain, arch.metaphysical_saved_rr0));
+       DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct exec_domain, arch.breakimm));
+       DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct exec_domain, arch.iva));
 
        BLANK();
 
index 65f245d870a1120898aed5159731fd81d3a3d9f1..b57a727a501cb5e9368838f1bae8b9f5648274a1 100644 (file)
@@ -50,7 +50,7 @@ void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned lon
 
        if (d == dom0) paddr += dom0_start;
        imva = domain_mpa_to_imva(d,paddr);
-       build_hypercall_bundle(imva,d->breakimm,hypercall,1);
+       build_hypercall_bundle(imva,d->arch.breakimm,hypercall,1);
 }
 
 
@@ -61,7 +61,7 @@ void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long
 
        if (d == dom0) paddr += dom0_start;
        imva = domain_mpa_to_imva(d,paddr);
-       build_hypercall_bundle(imva,d->breakimm,hypercall,ret);
+       build_hypercall_bundle(imva,d->arch.breakimm,hypercall,ret);
 }
 
 
index 30a7a45dd16efa59b95bfee23c8ed154f1272e08..cc879a4f6fbdff9853fd4b91970cf130f6ef453c 100644 (file)
@@ -210,7 +210,7 @@ void arch_do_createdomain(struct exec_domain *ed)
         */
        d->xen_vastart = 0xf000000000000000;
        d->xen_vaend = 0xf300000000000000;
-       d->breakimm = 0x1000;
+       d->arch.breakimm = 0x1000;
 
        // stay on kernel stack because may get interrupts!
        // ia64_ret_from_clone (which b0 gets in new_thread) switches
@@ -256,7 +256,8 @@ void arch_do_createdomain(struct exec_domain *ed)
        d->xen_vastart = 0xf000000000000000;
        d->xen_vaend = 0xf300000000000000;
        d->shared_info_va = 0xf100000000000000;
-       d->breakimm = 0x1000;
+       d->arch.breakimm = 0x1000;
+       ed->arch.breakimm = d->arch.breakimm;
        // stay on kernel stack because may get interrupts!
        // ia64_ret_from_clone (which b0 gets in new_thread) switches
        // to user stack
index a33518e0ac5720cc066ca74cb0cbf1251b367db4..cbb8b39e4ce16ae04c2cf095bd35125e1c39b67f 100644 (file)
@@ -62,6 +62,92 @@ GLOBAL_ENTRY(fast_hyperprivop)
        // if not one of the above, give up for now and do it the slow way
        br.sptk.many dispatch_break_fault ;;
 
+// reflect domain breaks directly to domain
+// FIXME: DOES NOT WORK YET
+//     r16 == cr.isr
+//     r17 == cr.iim
+//     r18 == XSI_PSR_IC
+//     r19 == vpsr.ic (low 32 bits) | vpsr.i (high 32 bits)
+//     r22 == IA64_KR(CURRENT)+IA64_VCPU_BREAKIMM_OFFSET
+//     r31 == pr
+GLOBAL_ENTRY(fast_break_reflect)
+       mov r20=cr.ipsr;;
+       // if big-endian domain or privileged-perfmon bits set, do slow way
+       extr.u r21=r20,IA64_PSR_BE_BIT,1 ;;
+       cmp.ne p7,p0=r21,r0
+(p7)   br.sptk.many dispatch_break_fault ;;
+       extr.u r21=r20,IA64_PSR_PP_BIT,1 ;;
+       cmp.ne p7,p0=r21,r0
+(p7)   br.sptk.many dispatch_break_fault ;;
+       // ensure ipsr.cpl==2, ipsr.ri==0
+       // FIXME: any other psr bits need to be properly set/validated?
+       //   ...see process.c: DELIVER_PSR_CLR/SET
+       extr.u r21=r20,IA64_PSR_CPL0_BIT,2;;
+       extr.u r23=r20,IA64_PSR_RI_BIT,2;;
+       dep r20=-1,r20,IA64_PSR_CPL1_BIT,1 ;;
+       dep r20=0,r20,IA64_PSR_CPL0_BIT,1 ;;
+       dep r20=0,r20,IA64_PSR_RI_BIT,2 ;;
+       mov cr.ipsr=r20;;
+       // save ipsr in shared_info, vipsr.cpl==(ipsr.cpl==3)?3:0
+       cmp.ne p7,p0=3,r21;;
+(p7)   mov r21=r0
+       dep r20=r21,r20,IA64_PSR_CPL0_BIT,2 ;;
+       dep r20=r23,r20,IA64_PSR_RI_BIT,2 ;;
+       // vipsr.i=vpsr.i
+       adds r21=XSI_PSR_I_OFS-XSI_PSR_IC_OFS,r18 ;;
+       ld4 r21=[r21];;
+       dep r20=r21,r20,IA64_PSR_I_BIT,1 ;;
+       adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;;
+       // FIXME: any other vpsr bits need to be properly set/validated?
+       st8 [r21]=r20;;
+       // save iim in shared_info
+       adds r21=XSI_IIM_OFS-XSI_PSR_IC_OFS,r18 ;;
+       st8 [r21]=r17;;
+       // save iip in shared_info
+       mov r20=cr.iip;;
+       adds r21=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;;
+       st8 [r21]=r20;;
+       // save ifs in shared_info
+       adds r21=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;;
+       st4 [r21]=r0 ;;
+       adds r21=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18
+       st8 [r21]=r0 ;;
+       cover ;;
+       mov r20=cr.ifs;;
+       adds r21=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;;
+       st8 [r21]=r20;;
+       // vpsr.i = vpsr.ic = 0 on delivery of interruption
+       st8 [r18]=r0;;
+       // FIXME: need to save iipa and isr to be arch-compliant
+       // set iip to go to domain IVA break instruction vector
+       adds r22=IA64_VCPU_IVA_OFFSET-IA64_VCPU_BREAKIMM_OFFSET,r22;;
+       ld8 r23=[r22];;
+       movl r24=0x2c00;;
+       add r24=r24,r23;;
+       mov cr.iip=r24;;
+       // OK, now all set to go except for switch to virtual bank0
+       mov r30=r2; mov r29=r3;;
+       adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18;
+       adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;;
+       bsw.1;;
+       st8 [r2]=r16,16; st8 [r3]=r17,16 ;;
+       st8 [r2]=r18,16; st8 [r3]=r19,16 ;;
+       st8 [r2]=r20,16; st8 [r3]=r21,16 ;;
+       st8 [r2]=r22,16; st8 [r3]=r23,16 ;;
+       st8 [r2]=r24,16; st8 [r3]=r25,16 ;;
+       st8 [r2]=r26,16; st8 [r3]=r27,16 ;;
+       st8 [r2]=r28,16; st8 [r3]=r29,16 ;;
+       st8 [r2]=r30,16; st8 [r3]=r31,16 ;;
+       movl r31=XSI_IPSR;;
+       bsw.0 ;;
+       mov r2=r30; mov r3=r29;;
+       adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;;
+       st4 [r20]=r0 ;;
+       mov pr=r31,-1 ;;
+       rfi
+       ;;
+
+
 // ensure that, if giving up, registers at entry to fast_hyperprivop unchanged
 ENTRY(hyper_rfi)
 #define FAST_HYPERPRIVOP_CNT
@@ -112,8 +198,6 @@ ENTRY(hyper_rfi)
        ld8 r20=[r20];;
        dep r20=0,r20,38,25;; // ensure ifs has no reserved bits set
        mov cr.ifs=r20 ;;
-// TODO: increment a counter so we can count how many rfi's go the fast way
-//    but where?  counter must be pinned
        // ipsr.cpl == (vcr.ipsr.cpl == 0) 2 : 3;
        dep r21=-1,r21,IA64_PSR_CPL1_BIT,1 ;;
        // vpsr.i = vcr.ipsr.i; vpsr.ic = vcr.ipsr.ic
index 0938f6075e65fa328c3293cf4c15cc46acd1ff0a..e78e7f96b9a1e458a757f5f55ec41e9fc93f57da 100644 (file)
@@ -783,20 +783,26 @@ ENTRY(break_fault)
        ld8 r19=[r18]
        ;;
        cmp.eq p7,p0=r0,r17                     // is this a psuedo-cover?
-(p7)   br.sptk.many dispatch_privop_fault
+(p7)   br.spnt.many dispatch_privop_fault
        ;;
-       cmp4.ne p7,p0=r0,r19
-(p7)   br.sptk.many dispatch_break_fault
-       // If we get to here, we have a hyperprivop
-       // For now, hyperprivops are handled through the break mechanism
-       // Later, they will be fast hand-coded assembly with psr.ic off
+       // if vpsr.ic is off, we have a hyperprivop
+       // A hyperprivop is hand-coded assembly with psr.ic off
        // which means no calls, no use of r1-r15 and no memory accesses
        // except to pinned addresses!
-#define FAST_HYPERPRIVOPS
-#ifdef FAST_HYPERPRIVOPS
-       br.sptk.many fast_hyperprivop
+       cmp4.eq p7,p0=r0,r19
+(p7)   br.sptk.many fast_hyperprivop
+       ;;
+       mov r22=IA64_KR(CURRENT);;
+       adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22;;
+       ld4 r23=[r22];;
+       cmp4.eq p6,p7=r23,r17                   // Xen-reserved breakimm?
+(p6)   br.spnt.many dispatch_break_fault
+       ;;
+//#define FAST_BREAK
+#ifdef FAST_BREAK
+       br.sptk.many fast_break_reflect
 #else
-       br.sptk.many dispatch_break_fault
+       br.spnt.many dispatch_break_fault
 #endif
        ;;
 #endif
index d0be05d9e4a2eb8d5963e4b10e7acc9716d6cfb6..c989eb1cbcbe599e8d12bdc57bd7c6498176970e 100644 (file)
@@ -987,14 +987,14 @@ int dump_hyperprivop_counts(char *buf)
        char *s = buf;
        unsigned long total = 0;
        for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += slow_hyperpriv_cnt[i];
-       s += sprintf(s,"Slow hyperprivops (total %d:\n",total);
+       s += sprintf(s,"Slow hyperprivops (total %d):\n",total);
        for (i = 1; i <= HYPERPRIVOP_MAX; i++)
                if (slow_hyperpriv_cnt[i])
                        s += sprintf(s,"%10d %s\n",
                                slow_hyperpriv_cnt[i], hyperpriv_str[i]);
        total = 0;
        for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += fast_hyperpriv_cnt[i];
-       s += sprintf(s,"Fast hyperprivops (total %d:\n",total);
+       s += sprintf(s,"Fast hyperprivops (total %d):\n",total);
        for (i = 1; i <= HYPERPRIVOP_MAX; i++)
                if (fast_hyperpriv_cnt[i])
                        s += sprintf(s,"%10d %s\n",
@@ -1016,6 +1016,7 @@ int dump_privop_counts_to_user(char __user *ubuf, int len)
        int n = dump_privop_counts(buf);
 
        n += dump_hyperprivop_counts(buf + n);
+       n += dump_reflect_counts(buf + n);
 #ifdef PRIVOP_ADDR_COUNT
        n += dump_privop_addrs(buf + n);
 #endif
@@ -1033,6 +1034,7 @@ int zero_privop_counts_to_user(char __user *ubuf, int len)
 #ifdef PRIVOP_ADDR_COUNT
        zero_privop_addrs();
 #endif
+       zero_reflect_counts();
        if (len < TMPBUFLEN) return -1;
        if (__copy_to_user(ubuf,buf,n)) return -1;
        return n;
index 60a2f30f76699a683c1b4f794788aadba84c7367..f1655b25809d4940545014137c03c94d1bb43ec1 100644 (file)
@@ -130,6 +130,42 @@ unsigned long translate_domain_mpaddr(unsigned long mpaddr)
        return ((pteval & _PAGE_PPN_MASK) | (mpaddr & ~PAGE_MASK));
 }
 
+unsigned long slow_reflect_count[0x80] = { 0 };
+unsigned long fast_reflect_count[0x80] = { 0 };
+
+#define inc_slow_reflect_count(vec) slow_reflect_count[vec>>8]++;
+
+void zero_reflect_counts(void)
+{
+       int i;
+       for (i=0; i<0x80; i++) slow_reflect_count[i] = 0;
+       for (i=0; i<0x80; i++) fast_reflect_count[i] = 0;
+}
+
+int dump_reflect_counts(char *buf)
+{
+       int i,j,cnt;
+       char *s = buf;
+
+       s += sprintf(s,"Slow reflections by vector:\n");
+       for (i = 0, j = 0; i < 0x80; i++) {
+               if (cnt = slow_reflect_count[i]) {
+                       s += sprintf(s,"0x%02x00:%10d, ",i,cnt);
+                       if ((j++ & 3) == 3) s += sprintf(s,"\n");
+               }
+       }
+       if (j & 3) s += sprintf(s,"\n");
+       s += sprintf(s,"Fast reflections by vector:\n");
+       for (i = 0, j = 0; i < 0x80; i++) {
+               if (cnt = fast_reflect_count[i]) {
+                       s += sprintf(s,"0x%02x00:%10d, ",i,cnt);
+                       if ((j++ & 3) == 3) s += sprintf(s,"\n");
+               }
+       }
+       if (j & 3) s += sprintf(s,"\n");
+       return s - buf;
+}
+
 void reflect_interruption(unsigned long ifa, unsigned long isr, unsigned long itiriim, struct pt_regs *regs, unsigned long vector)
 {
        unsigned long vcpu_get_ipsr_int_state(struct exec_domain *,unsigned long);
@@ -165,6 +201,7 @@ panic_domain(regs,"psr.ic off, delivering fault=%lx,iip=%p,ifa=%p,isr=%p,PSCB.ii
                regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
 // NOTE: nested trap must NOT pass PSCB address
                //regs->r31 = (unsigned long) &PSCB(ed);
+               inc_slow_reflect_count(vector);
                return;
 
        }
@@ -195,6 +232,8 @@ panic_domain(regs,"psr.ic off, delivering fault=%lx,iip=%p,ifa=%p,isr=%p,PSCB.ii
 
        PSCB(ed,interrupt_delivery_enabled) = 0;
        PSCB(ed,interrupt_collection_enabled) = 0;
+
+       inc_slow_reflect_count(vector);
 }
 
 void foodpi(void) {}
@@ -748,7 +787,7 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u
                if (running_on_sim) do_ssc(vcpu_get_gr(current,36), regs);
                else do_ssc(vcpu_get_gr(current,36), regs);
        }
-       else if (iim == d->breakimm) {
+       else if (iim == d->arch.breakimm) {
                if (ia64_hypercall(regs))
                        vcpu_increment_iip(current);
        }
index d361b3409020b007e7817dde7cd56bc167fd3f9e..88de406adcdcd24676e9e16488a41a7e9533e5fe 100644 (file)
@@ -49,7 +49,6 @@ struct arch_domain {
 #define starting_rid arch.starting_rid
 #define ending_rid arch.ending_rid
 #define rid_bits arch.rid_bits
-#define breakimm arch.breakimm
 #define xen_vastart arch.xen_vastart
 #define xen_vaend arch.xen_vaend
 #define shared_info_va arch.shared_info_va
@@ -75,6 +74,7 @@ struct arch_exec_domain {
     void *regs;        /* temporary until find a better way to do privops */
     int metaphysical_rr0;              // from arch_domain (so is pinned)
     int metaphysical_saved_rr0;                // from arch_domain (so is pinned)
+    int breakimm;                      // from arch_domain (so is pinned)
     struct mm_struct *active_mm;
     struct thread_struct _thread;      // this must be last
 #ifdef CONFIG_VTI